﻿using System;
using System.Linq;
using System.Reflection;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace MvcSimplyCleverPart3
{
    public class LocalizableControllerNameMvcRouteHandler : MvcRouteHandler
    {
        protected override IHttpHandler GetHttpHandler(RequestContext requestContext)
        {
            string localizedControllerName = requestContext.RouteData.Values["Controller"].ToString();

            requestContext.RouteData.Values["Controller"] = this.GetFallbackControllerName(localizedControllerName);

            return base.GetHttpHandler(requestContext);
        }

        private string GetFallbackControllerName(string localizedControllerName)
        {
            Type controllerType = (from t in Assembly.GetExecutingAssembly().GetTypes()
                                      where t.Name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase) &&
                                      TypeUtilities.InheritsFrom(t, typeof(Controller)) &&
                                      ControllerNameMatches(t, localizedControllerName)
                                      select t).FirstOrDefault();

            if (controllerType == null)
            {
                // There is no controller that matches this localized name so the name has not been localized.
                // Proceed as normal using the original controller name.
                return localizedControllerName;
            }

            string fallbackControllerName = controllerType.Name;

            // strip the word "Controller" from the end of the name
            fallbackControllerName = fallbackControllerName.Substring(0, fallbackControllerName.Length - 10);
            return fallbackControllerName;
        }

        private bool ControllerNameMatches(Type controllerType, string localizedControllerName)
        {
            object[] localizableControllerNameAttributes = controllerType.GetCustomAttributes(typeof(LocalizableControllerNameAttribute), true);
            if (localizableControllerNameAttributes.GetLength(0) == 0)
            {
                // this type does not have a localizable controller name attribute
                return false;
            }

            LocalizableControllerNameAttribute localizableControllerNameAttribute = (LocalizableControllerNameAttribute)localizableControllerNameAttributes[0];
            return String.Compare(localizableControllerNameAttribute.LocalizedControllerName, localizedControllerName, true) == 0;
        }
    }
}